iT邦幫忙

2022 iThome 鐵人賽

DAY 19
0
Modern Web

為期 N 天的 react 小冒險系列 第 19

用 react hook 寫一個簡易計算機吧-中-day19

  • 分享至 

  • xImage
  •  

昨天剛寫完樣式,今天來處理一下按鍵輸入數字的事件
一樣在 Calculator.js 這個父元件中處理..

因為在計算機的螢幕上要顯示 1+1*2 這樣的格式,所以 state.calcProgress 格式為 string

按下數字 (0-9)

執行 dispatch({ type: "該按鈕的數值" });
dispatch 的引數 action 則傳到 reducer function 中,再根據傳入的數字格式而添加到 state.calcProgress 的尾端,最後再回傳整個 state object

按下 c

不管狀態為何,就直接把 state.calcProgress 歸為 '0'

Calculator.js

import { useReducer } from "react";
import CalcButton from "./CalcButton";
import Result from "./Result";

const INITIAL_STATE = { calcProgress: "0" };

export default function Calculator() {
  const [calcResult, dispatch] = useReducer(reducer, INITIAL_STATE);

  function reducer(state, action) {
    let lastAlphabet = state.calcProgress[state.calcProgress.length - 1];
    console.log({ ...state });
    switch (action.type) {
      // if lastAlphabet is +-*/ next +-*/ will replace it
      case "+":
        break;
      case "-":
        break;
      case "*":
        break;
      case "/":
        break;
      case "=":
        break;
      case ".":
        // 不能出現 .. 這種情況,其他都可以
        if (lastAlphabet === ".") {
          return { calcProgress: state.calcProgress };
        } else {
          return { calcProgress: state.calcProgress + "." };
        }
      case "c":
        // state.calcProgress reset to 0
        return { calcProgress: "0" };
      case 0:
        return keyNumber(state.calcProgress, "0");
      case 1:
        return keyNumber(state.calcProgress, "1");
      case 2:
        return keyNumber(state.calcProgress, "2");
      case 3:
        return keyNumber(state.calcProgress, "3");
      case 4:
        return keyNumber(state.calcProgress, "4");
      case 5:
        return keyNumber(state.calcProgress, "5");
      case 6:
        return keyNumber(state.calcProgress, "6");
      case 7:
        return keyNumber(state.calcProgress, "7");
      case 8:
        return keyNumber(state.calcProgress, "8");
      case 9:
        return keyNumber(state.calcProgress, "9");
      default:
        throw new Error("some error happened");
    }
  }

  function keyNumber(currentStr, targetNumString) {
    // 如果首位是0且只有0ㄧ位 則按下的數值取代首位
    // 如果首位非零且不只一位 則在currentStr後增加'0'(string)
    let returnNumStr = "";
    currentStr === "0"
      ? (returnNumStr = { calcProgress: targetNumString })
      : (returnNumStr = {
          calcProgress: currentStr.concat(targetNumString)
        });
    return returnNumStr;
  }

  function handleCalculate(currentStr) {
    let result = eval(currentStr).toString();
    return { calcProgress: result };
  }

  return (
    <div className="calculator-wrap">
      <Result content={calcResult.calcProgress} />
      <div className="d-flex btn-wrap">
        <CalcButton
          action="c"
          onClick={() => {
            dispatch({ type: "c" });
          }}
        />
      </div>
      <div className="d-flex btn-wrap">
        <CalcButton
          action="7"
          onClick={() => {
            dispatch({ type: 7 });
          }}
        />
        <CalcButton
          action="8"
          onClick={() => {
            dispatch({ type: 8 });
          }}
        />
        <CalcButton
          action="9"
          onClick={() => {
            dispatch({ type: 9 });
          }}
        />
        <CalcButton
          action="/"
          onClick={() => {
            dispatch({ type: "/" });
          }}
        />
      </div>
      <div className="d-flex btn-wrap">
        <CalcButton
          action="4"
          onClick={() => {
            dispatch({ type: 4 });
          }}
        />
        <CalcButton
          action="5"
          onClick={() => {
            dispatch({ type: 5 });
          }}
        />
        <CalcButton
          action="6"
          onClick={() => {
            dispatch({ type: 6 });
          }}
        />
        <CalcButton
          action="*"
          onClick={() => {
            dispatch({ type: "*" });
          }}
        />
      </div>
      <div className="d-flex btn-wrap">
        <CalcButton
          action="1"
          onClick={() => {
            dispatch({ type: 1 });
          }}
        />
        <CalcButton
          action="2"
          onClick={() => {
            dispatch({ type: 2 });
          }}
        />
        <CalcButton
          action="3"
          onClick={() => {
            dispatch({ type: 3 });
          }}
        />

        <CalcButton
          action="-"
          onClick={() => {
            dispatch({ type: "-" });
          }}
        />
      </div>
      <div className="d-flex btn-wrap">
        <CalcButton action="0" />
        <CalcButton
          action="."
          onClick={() => {
            dispatch({ type: "." });
          }}
        />
        <CalcButton
          action="="
          onClick={() => {
            dispatch({ type: "=" });
          }}
        />
        <CalcButton
          action="+"
          onClick={() => {
            dispatch({ type: "+" });
          }}
        />
      </div>
    </div>
  );
}

鍵入數字這回事暫時是完成了xd

接下來繼續寫 加,減,乘,除,等於(運算結果) 這些事件..


上一篇
用 react hook 寫一個簡易計算機吧-上-day18
下一篇
用 react hook 寫一個簡易計算機吧-下-day20
系列文
為期 N 天的 react 小冒險30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言